%{ open Ast_TablePro %}
%token  EOF 
%token  <float> NUMBER 
%token  <int> INTCONST
%token  <string> IDENTIFIER 
%token  <string> SIMPLETYPE
%token  <string> COMPTYPE
%token  COMMA
%token  ADD
%token  SUBTRACT
%token  MULTIPLY
%token  DIVIDE
%token  ASSIGN        
%token  SIZE
%token  CURRINDEX
%token  IF
%token  ELSE
%token  LEFTPARAN
%token  RIGHTPARAN
%token  LEFTSQPARAN
%token  RIGHTSQPARAN
%token  LEFTPARAN
%token  BLOCKBEGIN
%token  BLOCKEND
%token  LOOP
%token  GREATERTHAN
%token  LESSTHAN
%token  EQUALITY
%token  LOGICALAND
%token  LOGICALOR
%token  FUNCTION
%token  COL_HEADING
%token  ROW_HEADING
%token  ROW_LIMIT
%token  COL_LIMIT
%token  ROW_FILTER_CONDITION
%token  COL_SORT_INDEX
%token  RETURN	
%token  <string> STRCONST
%token  SEMICOLON
%token  BOGUS
%token  DOT
%token  SIZE 
%token  GENERATE_TABLE

%left INTCONST 
%right ASSIGN
%left GREATERTHAN LESSTHAN EQUALITY
%left LOGICALAND LOGICALOR
%left ADD  SUBTRACT
%left MULTIPLY DIVIDE


%nonassoc NOELSE
%nonassoc ELSE

%start program
%type <Ast_TablePro.program> program
%%

expr:   
	 genExpr {$1 }

	 
primaryexpr:
   NUMBER { Literal($1) }
| INTCONST { IntLiteral ($1)}
| IDENTIFIER { Id($1) }
| STRCONST { StrLiteral($1) }


genExpr:
  genExpr ADD genExpr { Binop($1, Add, $3) }
| genExpr SUBTRACT genExpr { Binop($1, Sub, $3) }
| genExpr MULTIPLY genExpr { Binop($1, Mult, $3) }
| genExpr DIVIDE genExpr { Binop($1, Div, $3) }
| genExpr GREATERTHAN genExpr {Binop($1, Greater, $3) }
| genExpr LESSTHAN genExpr {Binop($1, Less, $3) }
| genExpr EQUALITY genExpr {Binop($1, Equality, $3) }
| genExpr LOGICALAND genExpr {Binop($1, And, $3) }
| genExpr LOGICALOR genExpr {Binop($1, Or, $3) }
| IDENTIFIER ASSIGN genExpr {Assign( $1, $3) } 
| indexExpr {$1 }
| indexRelExpr {$1 }
| IDENTIFIER LEFTPARAN argList RIGHTPARAN {Call ($1, $3) }
| NUMBER { Literal($1) }
| INTCONST { IntLiteral ($1)}
| IDENTIFIER { Id($1) }
| STRCONST { StrLiteral($1) }



indexExpr:

  IDENTIFIER LEFTSQPARAN primaryexpr RIGHTSQPARAN ASSIGN genExpr { IndexAsn($1, $3 , $6) }
| IDENTIFIER LEFTSQPARAN primaryexpr RIGHTSQPARAN {Index($1, $3)}
| IDENTIFIER DOT SIZE {IndexSize($1)}

	

indexRelExpr:
	IDENTIFIER LEFTSQPARAN primaryexpr SUBTRACT primaryexpr RIGHTSQPARAN  ADD ASSIGN genExpr {IndexRange($1, $3, $5, Add, $9)}
	| IDENTIFIER LEFTSQPARAN primaryexpr SUBTRACT primaryexpr RIGHTSQPARAN  SUBTRACT ASSIGN genExpr {IndexRange($1, $3, $5,Sub,  $9)}
	| IDENTIFIER LEFTSQPARAN primaryexpr SUBTRACT primaryexpr RIGHTSQPARAN  MULTIPLY ASSIGN genExpr {IndexRange($1, $3, $5, Mult, $9)}
	| IDENTIFIER LEFTSQPARAN primaryexpr SUBTRACT primaryexpr RIGHTSQPARAN  DIVIDE ASSIGN genExpr {IndexRange($1, $3, $5, Div, $9)}	
	
argList:  argList COMMA genExpr {List.rev($3::$1)}
	  | genExpr {[$1]}
	  



stmnt:
 	sdeclstmnt{  $1 }
 	| cdeclstmnt{  $1 }
 	| cdeclAsnstmnt{ $1 }
	| exprstmnt {$1}
	| blockstmnt{$1 } 
	| condstmnt{$1 }
	| iterstmnt{$1 } 
	| returnstmnt{$1 }
	| funcdeclstmnt{ $1 }
	| gentablestmnt {$1 }


gentablestmnt: GENERATE_TABLE identifierList SEMICOLON {GenerateStmnt($2)};
		
identifierList: identifierList COMMA IDENTIFIER { $3::$1 }
		| IDENTIFIER {[$1]};
		

sdeclstmnt:
	SIMPLETYPE IDENTIFIER SEMICOLON{ SDeclstmnt($1, $2) }
	
cdeclstmnt:
	COMPTYPE IDENTIFIER LESSTHAN SIMPLETYPE COMMA STRCONST GREATERTHAN SEMICOLON{CDeclstmnt($1, $4, $6, $2)}
	
cdeclAsnstmnt:
	 COMPTYPE IDENTIFIER LESSTHAN SIMPLETYPE COMMA STRCONST GREATERTHAN  ASSIGN BLOCKBEGIN strconstList BLOCKEND SEMICOLON {CStrdeclAsnstmnt ($1, $4, $6, $2, $10)}
	| COMPTYPE IDENTIFIER LESSTHAN SIMPLETYPE COMMA STRCONST GREATERTHAN  ASSIGN BLOCKBEGIN numberList BLOCKEND SEMICOLON {CNumdeclAsnstmnt ($1, $4, $6, $2, $10)}
	
	
strconstList: STRCONST COMMA strconstList {$1::$3}
		| STRCONST {[$1] }
		

numberList: NUMBER COMMA numberList {$1::$3}
	| NUMBER {[$1]}
	
exprstmnt:
	expr SEMICOLON {Stmnt($1)}

blockstmnt: 
  BLOCKBEGIN stmnt_list BLOCKEND {Block(List.rev($2)) }
  
stmnt_list:
 		stmnt_list stmnt {($2::$1)}
 		| stmnt {[$1]}


condstmnt:
	 IF LEFTPARAN genExpr RIGHTPARAN BLOCKBEGIN stmnt_list BLOCKEND ELSE BLOCKBEGIN stmnt_list BLOCKEND { If ($3, List.rev($6), List.rev($10))}
	 | IF LEFTPARAN genExpr RIGHTPARAN BLOCKBEGIN stmnt_list BLOCKEND %prec NOELSE { If($3, List.rev($6), []) }


iterstmnt:
   LOOP LEFTPARAN genExpr RIGHTPARAN BLOCKBEGIN stmnt_list BLOCKEND{Loop ($3, List.rev($6))}

returnstmnt:
	 RETURN IDENTIFIER SEMICOLON{ Return($2)}
	| RETURN SEMICOLON {Return("")}


funcdeclstmnt:
 	FUNCTION IDENTIFIER LEFTPARAN fargList RIGHTPARAN rettype BLOCKBEGIN stmnt_list BLOCKEND 
 	 {Func_decl($2, $4, $6, List.rev $8) }
 	 
rettype: SIMPLETYPE  {Sret($1)}
	| COMPTYPE LESSTHAN SIMPLETYPE GREATERTHAN { Cret($1, $3)} 	 
  
fargList:  fargList COMMA farg {List.rev($3::$1)}
	  | farg {[$1]}
	  
farg:   SIMPLETYPE IDENTIFIER {Sarg($1,$2)}
	| COMPTYPE IDENTIFIER LESSTHAN SIMPLETYPE COMMA STRCONST GREATERTHAN { Carg ($1, $2, $4,$6)}


program : 
		/* nothing */ { [] }
	  | stmnt_list { List.rev $1}

	  

